#include "LonLatUtil.h"
#include "math.h"
#include <QDebug>
#include <QtMath>

using namespace ns_yht;

LonLatUtil::LonLatUtil()
{
}

LonLatUtil::~LonLatUtil()
{
}

void LonLatUtil::toDMS(double value, int &degree, int &minute, double &second)
{
    bool isNegative = value < 0;
    value = abs(value);
    degree = floor(value);
    double decimalRemainder = fabs(value - degree);
    minute = floor(decimalRemainder * 60);
    second = (decimalRemainder * 60 - minute) * 60;

    if (second >= 59.995)
    {
        second = 0;
        minute++;
        if (minute == 60)
        {
            minute = 0;
            degree++;
        }
    }

    if (isNegative)
    {
        degree = -degree;
    }
}

void LonLatUtil::toDM(double value, int &degree, double &minute)
{
    bool isNegative = value < 0;
    value = abs(value);
    degree = floor(value);
    double decimalRemainder = fabs(value - degree);
    minute = decimalRemainder * 60;

    if (minute >= 59.99995)
    {
        minute = 0;
        degree++;
    }

    if (isNegative)
    {
        degree = -degree;
    }
}

double LonLatUtil::toReal(int degree, int minute, double second)
{
    return degree + minute / 60.0 + second / 3600.0;
}

double LonLatUtil::toReal(int degree, double minute)
{
    return degree + minute / 60.0;
}

QString LonLatUtil::toString_sn(double value, bool isLon)
{
    int degree;
    int minute;
    double second;
    toDMS(value, degree, minute, second); // 123°45'56.78"
    degree = abs(degree);
    bool isNegative = value < 0;

    return QString("%1°%2′%3″%4").arg(degree, 3, 10, QChar(' ')).arg(minute, 2, 10, QChar('0')).arg(second, 5, 'f', 2, QChar('0')).arg(isNegative ? (isLon ? "W" : "S") : (isLon ? "E" : "N"));
}

QString LonLatUtil::toString_cn(double value, bool isLon)
{
    int degree, minute;
    double second;
    toDMS(value, degree, minute, second);
    degree = abs(degree);
    bool isNegative = value < 0;
    return QString("%1%2度%3分%4秒").arg(isNegative ? (isLon ? "西经" : "南纬") : (isLon ? "东经" : "北纬")).arg(degree, 3, 10, QChar(' ')).arg(minute, 2, 10, QChar('0')).arg(second, 5, 'f', 2, QChar('0'));
}

bool LonLatUtil::isValid(qreal lat, qreal lon)
{
    return (lat > -90 && lat <= 90 && lon > -180 && lon <= 180);
}

bool LonLatUtil::isValid(const QPair<double, double> &coor)
{
    return isValid(coor.first, coor.second);
}

double LonLatUtil::toReal(const QString &scoor)
{
    if (scoor == "")
        return 181;
    QStringList s3s = scoor.split(QRegExp("[°′]"));
    if (s3s.count() < 2)
    {
        qInfo() << "Invalid coordinate format------------" << scoor;
        return 181;
    }
    qreal coor = s3s[0].toInt() + s3s[1].toDouble() / 60;
    if (s3s.count() >= 3 && s3s[2] == "W" || s3s[2] == "S")
        coor = -coor;

    return coor;
}

QString LonLatUtil::toString(const QPair<double, double> &coor)
{
    return QString("%1,%2").arg(coor.first).arg(coor.second);
}

QString LonLatUtil::toString(double lat, double lon)
{
    return QString("%1,%2").arg(lat).arg(lon);
}

void LonLatUtil::fromString(const QString &scoor, double &lat, double &lon)
{
    QStringList ss = scoor.split(',');
    int n = ss.count();
    if (n > 0)
        lat = ss.at(0).toDouble();
    if (n > 1)
        lon = ss.at(1).toDouble();
}

QPair<double, double> LonLatUtil::fromString(const QString &scoor)
{
    double lat, lon;
    fromString(scoor, lat, lon);
    return QPair<double, double>(lat, lon);
}
// 将字符串转换为经纬度数值
// typeInt = 0, lonlatString = ddmm.mmmm或者ddmm.mmm
// typeInt = 1, timeString = dddmm.mmmm或者dddmm.mmm

double LonLatUtil::getLonlat(const QString lonlatString, const int typeInt)
{
    double returnDoubl = 0;
    int degreeInt = 0;
    int lengthInt = 0;
    double minuteDouble = 0;

    if (typeInt == 0)
    {
        degreeInt = lonlatString.left(2).toInt();
        lengthInt = lonlatString.length() - 2;
        minuteDouble = lonlatString.mid(2, lengthInt).toDouble();
        returnDoubl = degreeInt + minuteDouble / 60.0;
    }
    else if (typeInt == 1)
    {
        degreeInt = lonlatString.left(3).toInt();
        lengthInt = lonlatString.length() - 3;
        minuteDouble = lonlatString.mid(3, lengthInt).toDouble();
        returnDoubl = degreeInt + minuteDouble / 60.0;
    }

    return returnDoubl;
}

double LonLatUtil::getLat(const QByteArray &latString, const QByteArray &nsIndicator)
{
    double lat = latString.toDouble();
    int degree = qFloor(lat / 100);
    lat = degree + (lat - degree * 100) / 60;
    if (nsIndicator == "S")
        lat = -lat;
    return lat;
}

double LonLatUtil::getLon(const QByteArray &lonString, const QByteArray &ewIndicator)
{
    double lon = lonString.toDouble();
    int degree = qFloor(lon / 100);
    lon = degree + (lon - degree * 100) / 60;
    if (ewIndicator == "W")
        lon = -lon;
    return lon;
}
